package com.github.cakin.shiro.chapter19.realm;

import com.github.cakin.shiro.chapter19.entity.User;
import com.github.cakin.shiro.chapter19.service.UserService;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @className: UserRealm
 * @description: UserRealm 用户Realm
 * @date: 2020/5/19
 * @author: cakin
 */
public class UserRealm extends AuthorizingRealm {

    /**
     * 注入用户服务
     */
    @Autowired
    private UserService userService;


    /**
     * 功能描述：获得授权信息
     *
     * @param principals 是一个身份集合
     * @return AuthorizationInfo 授权信息
     * @author cakin
     * @date 2020/5/19
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals ) {
        // 从输入获得用户名
        String username = (String) principals.getPrimaryPrincipal();

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 用户对应的角色列表
        authorizationInfo.setRoles(userService.findRoles(username));
        // 用户对应的权限列表
        authorizationInfo.setStringPermissions(userService.findPermissions(username));
        // 返回授权信息
        return authorizationInfo;
    }

    /**
     * 功能描述：获取身份验证信息
     *
     * @param token 用户的token
     * @return AuthenticationInfo 认证信息
     * @author cakin
     * @date 2020/5/19
     * @description: 从数据库获得认证数据
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token ) throws AuthenticationException {
        // 获得用户身份
        String username = (String) token.getPrincipal();
        // 用户详情
        User user = userService.findByUsername(username);

        if (user == null) {
            // 没找到帐号
            throw new UnknownAccountException();
        }

        if (Boolean.TRUE.equals(user.getLocked())) {
            // 帐号锁定
            throw new LockedAccountException();
        }

        // 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user.getUsername(), // 身份信息（用户名）
                user.getPassword(), // 凭据（密文密码）
                ByteSource.Util.bytes(user.getCredentialsSalt()), // salt=username+salt
                getName() //realm name
        );
        // 返回认证信息，交给间接父类 AuthenticatingRealm 使用 CredentialsMatcher 进行判断密码是否匹配
        return authenticationInfo;
    }

    /**
     * 功能描述：清理用户的授权缓存
     *
     * @author cakin
     * @date 2020/5/26
     * @param principals 用户身份
     */
    @Override
    public void clearCachedAuthorizationInfo( PrincipalCollection principals ) {
        super.clearCachedAuthorizationInfo(principals);
    }
    /**
     * 功能描述：清理用户的权限缓存
     *
     * @author cakin
     * @date 2020/5/26
     * @param principals 用户身份
     */
    @Override
    public void clearCachedAuthenticationInfo( PrincipalCollection principals ) {
        super.clearCachedAuthenticationInfo(principals);
    }
    /**
     * 功能描述：清理用户的认证缓存和权限缓存
     *
     * @author cakin
     * @date 2020/5/26
     * @param principals 用户身份
     */
    @Override
    public void clearCache( PrincipalCollection principals ) {
        super.clearCache(principals);
    }
    /**
     * 功能描述：清理所有用户的权限缓存
     *
     * @author cakin
     * @date 2020/5/26
     */
    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }
    /**
     * 功能描述：清理所有用户的认证缓存
     *
     * @author cakin
     * @date 2020/5/26
     */
    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }
    /**
     * 功能描述：清理所有用户的认证缓存和权限缓存
     *
     * @author cakin
     * @date 2020/5/26
     */
    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }

}
